#include "../Include/LogStream.h"

CLogLocator::CLogLocator(const char* szFile, uint32_t nLine)
{
    m_szFile = szFile;
    m_nLine = nLine;
}

CLogLocator::~CLogLocator()
{
}

//////////////////////////////////////////////////////////////////////////////////////////
CLogStream::CLogStream(E_LOG_LEVEL eLevel, const CLogLocator& rLogLocator)
{
    auto now = std::chrono::system_clock::now();
    std::time_t   now_time_t = std::chrono::system_clock::to_time_t(now);
    std::tm now_tm{};
    localtime_s(&now_tm, &now_time_t);
    auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
    char szTime[27] = { 0 };
    strftime(szTime, sizeof(szTime), "[%Y-%m-%d %H:%M:%S", &now_tm);
    snprintf(szTime + strlen(szTime), sizeof(szTime) - strlen(szTime), ".%03ld]", static_cast<long>(milliseconds.count()));

    m_strLogHead = szTime + std::string(" [") + std::string(GetLogLevelString(eLevel)) + "]";

    if (CLogSystem::Instance().IsHasFileInfo())
    {
        m_strLogHead += " [" + std::string(rLogLocator.m_szFile) +  ":" + std::to_string(rLogLocator.m_nLine) + "]";
    }

    if (CLogSystem::Instance().IsHasPid())
    {
        auto tid = std::this_thread::get_id();
        std::stringstream s;
        s << tid;
        m_strLogHead += " [" + s.str() + "]";
    }

    m_eLevel = eLevel;
}

CLogStream::~CLogStream()
{
    CByteArray byteArray;
    if (m_eLevel == E_LOG_LEVEL::LOG_LEVEL_DUMP)
    {
        std::string strLog = String2Hex(m_strMsg);
        byteArray.m_strMsg = m_strLogHead + " " + strLog + "\n";
        std::cout << strLog << '\n';
    }
    else 
    {
        byteArray.m_strMsg = m_strLogHead  + " " + m_strMsg + "\n";
        std::cout << m_strMsg << '\n';
    }
    CLogWriter::Instance().WriteLog(byteArray);
}

std::string CLogStream::String2Hex(const std::string& str)
{
    std::string strResult;
    for (size_t i = 0; i < str.size(); i++)
    {
        char szValue[4];
        memset(szValue, 0, sizeof(szValue));
        snprintf(szValue, sizeof(szValue), "%02X ", (uint8_t)str[i]);
        strResult += szValue;
    }
    return strResult;
}

CLogStream& CLogStream::operator<<(bool bArg)
{
    if (bArg)
    {
        m_strMsg += " true";
    }
    else
    {
        m_strMsg += " false";
    }
    return *this;
}

CLogStream& CLogStream::operator<<(char cArg)
{
    m_strMsg += cArg;
    return *this;
}

CLogStream& CLogStream::operator<<(int16_t n16Arg)
{
    m_strMsg += std::to_string(n16Arg);
    return *this;
}

CLogStream& CLogStream::operator<<(uint16_t u16Arg)
{
    m_strMsg += std::to_string(u16Arg);
    return *this;
}

CLogStream& CLogStream::operator<<(int32_t n32Arg)
{
    m_strMsg += std::to_string(n32Arg);
    return *this;
}

CLogStream& CLogStream::operator<<(uint32_t u32Arg)
{
    m_strMsg += std::to_string(u32Arg);
    return *this;
}

CLogStream& CLogStream::operator<<(int64_t n64Arg)
{
    m_strMsg += std::to_string(n64Arg);
    return *this;
}

CLogStream& CLogStream::operator<<(uint64_t u64Arg)
{
    m_strMsg += std::to_string(u64Arg);
    return *this;
}

CLogStream& CLogStream::operator<<(double dArg)
{
    m_strMsg += std::to_string(dArg);
    return *this;
}

CLogStream& CLogStream::operator<<(const char* szArg)
{
    m_strMsg += szArg;
    return *this;
}

CLogStream& CLogStream::operator<<(const std::string& strArg)
{
    m_strMsg += strArg;
    return *this;
}


